package api

import (
	"cloud-entropy-storage-system/common/pkg/crc"
	"cloud-entropy-storage-system/common/pkg/mime"
	"cloud-entropy-storage-system/common/pkg/read"
	"cloud-entropy-storage-system/common/pkg/resp"
	"cloud-entropy-storage-system/server/internal/svc"
	"fmt"
	"net/http"
	"path"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

func (f *FileLogic) GetFile() gin.HandlerFunc {
	return func(c *gin.Context) {
		dst := c.Param("path")
		data, fName, size, err := f.svcCtx.GetFile(dst)
		if err != nil {
			resp.ErrorResp(c).SetMsg(err.Error()).WriteErrJsonExit(http.StatusInternalServerError)
			return
		}
		c.Writer.Header().Set("Content-Type", mime.GetContentType(fName))
		c.Writer.Header().Set("Accept-Ranges", "bytes")
		c.Writer.Header().Set("Content-Length", strconv.Itoa(size))
		_, _ = c.Writer.Write(data)
		c.Writer.(http.Flusher).Flush()
	}
}

func (f *FileLogic) DeleteFile() gin.HandlerFunc {
	return func(c *gin.Context) {
		dst := c.Param("path")
		if err := f.svcCtx.DeleteFile(dst); err != nil {
			resp.ErrorResp(c).SetMsg(err.Error()).WriteJsonExit()
			return
		}
		resp.SuccessResp(c).WriteJsonExit()
	}
}

func (f *FileLogic) Upload() gin.HandlerFunc {
	return func(c *gin.Context) {
		fi, h, err := c.Request.FormFile("file")
		if err != nil {
			f.log.Error("c.Request.FormFile", zap.Error(err))
			resp.ErrorResp(c).SetMsg(err.Error()).WriteErrJsonExit(http.StatusBadRequest)
			return
		}
		defer fi.Close()
		dstPath := c.Param("path")
		dst := svc.CheckFileName(dstPath, h.Filename)
		if !strings.HasPrefix(dst, "/") {
			dst = fmt.Sprintf("/%s", dst)
		}
		md5, data := read.ByMultipart(fi, int(h.Size))
		crcCode := crc.GetCrc32(data)
		err = f.svcCtx.Upload(md5, data, crcCode, h, dst)
		if err != nil {
			resp.ErrorResp(c).SetMsg(err.Error()).WriteErrJsonExit(http.StatusBadRequest)
			return
		}
		resp.SuccessResp(c).WriteJsonExit()
	}
}

func (f *FileLogic) List() gin.HandlerFunc {
	return func(c *gin.Context) {
		page, _ := strconv.Atoi(c.DefaultQuery("page", "0"))
		limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
		data, err := f.svcCtx.List(page, limit, f.cfg.HttpHost)
		if err != nil {
			resp.ErrorResp(c).SetMsg(err.Error()).WriteErrJsonExit(http.StatusInternalServerError)
			return
		}
		resp.SuccessResp(c).SetCode(0).SetCount(f.svcCtx.Count()).SetData(data).WriteJsonExit()
	}
}

func (f *FileLogic) UploadV2() gin.HandlerFunc {
	return func(c *gin.Context) {
		fi, h, err := c.Request.FormFile("file")
		if err != nil {
			f.log.Error("c.Request.FormFile", zap.Error(err))
			resp.ErrorResp(c).SetMsg(err.Error()).WriteErrJsonExit(http.StatusBadRequest)
			return
		}
		defer fi.Close()
		dstPath := c.Param("path")
		dst := svc.CheckFileName(dstPath, h.Filename)
		if !strings.HasPrefix(dst, "/") {
			dst = fmt.Sprintf("/%s", dst)
		}
		err = f.svcCtx.UploadV2(fi, h, path.Join("./assets/bootstrap/upload", dst)) // 对dst进行url编码
		if err != nil {
			resp.ErrorResp(c).SetMsg(err.Error()).WriteErrJsonExit(http.StatusBadRequest)
			return
		}
		resp.SuccessResp(c).WriteJsonExit()
	}
}
